package com.ygqh.baby.handler;

import com.ygqh.baby.ao.PromotionType;
import com.ygqh.baby.model.CarPricesResult;
import com.ygqh.baby.model.CarPromotionWrapper;
import com.ygqh.baby.model.ShoppingCarBasicData;
import com.ygqh.baby.model.ShoppingCarDisPrice;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 〈购物车金额分摊处理器〉
 *
 * @author guohao
 * @date 2019/5/5 17:33
 * @since 1.0.0
 */
public class CarApportionPriceHandler {

    /**
     * 计算购物车各种优惠
     *
     * @param carList 购物车
     * @return CarPricesResult
     */
    public static CarPricesResult calculateCarDisPrice(List<CarPromotionWrapper> carList) {
        BigDecimal totalProductPrice = BigDecimal.ZERO;
        BigDecimal totalSpecialPrice = BigDecimal.ZERO;
        BigDecimal totalPackDisPrice = BigDecimal.ZERO;
        BigDecimal totalNewCustomDisPrice = BigDecimal.ZERO;
        BigDecimal totalVipDisPrice = BigDecimal.ZERO;
        BigDecimal totalBmdismDisPrice = BigDecimal.ZERO;
        for (CarPromotionWrapper shoppingCarModelWithPTag : carList) {
            ShoppingCarDisPrice carDisPrice = shoppingCarModelWithPTag.getCarDisPrice();
            totalProductPrice = totalProductPrice.add(carDisPrice.getProductPrice());
            totalPackDisPrice = totalPackDisPrice.add(carDisPrice.getPackDisPrice());
            totalBmdismDisPrice = totalBmdismDisPrice.add(carDisPrice.getBmdismDisPrice());
            totalSpecialPrice = totalSpecialPrice.add(carDisPrice.getSpecialPrice());
            totalNewCustomDisPrice = totalNewCustomDisPrice.add(carDisPrice.getNewCustomDisPrice());
            totalVipDisPrice = totalVipDisPrice.add(carDisPrice.getVipDisPrice());
        }
        CarPricesResult carPricesResult = new CarPricesResult();
        carPricesResult.setProductPrice(totalProductPrice);
        carPricesResult.setPackDisPrice(totalPackDisPrice);
        carPricesResult.setBmdisPrice(totalBmdismDisPrice);
        carPricesResult.setSpecialPrice(totalSpecialPrice);
        carPricesResult.setNewCustomDisPrice(totalNewCustomDisPrice);
        carPricesResult.setVipDisPrice(totalVipDisPrice);
        return carPricesResult;
    }

    /**
     * 获取参与满减的金额
     *
     * @param carPricesResult 购物车金额信息
     * @return BigDecimal
     */
    private static BigDecimal getManjianValidPrice(CarPricesResult carPricesResult) {
        return carPricesResult.getProductPrice().subtract(carPricesResult.getPackDisPrice()).subtract(carPricesResult.getVipDisPrice())
                .subtract(carPricesResult.getBmdisPrice()).subtract(carPricesResult.getNewCustomDisPrice());

    }

    /**
     * 计算每条购物车 促销优惠信息（自选包，多买多则，新客，会员优惠）
     *
     * @param carPromotionWrapperList 购物车 包装类
     * @param vip                     是否为vip
     * @param newCustms               是否新客
     * @param distribution            是否分销
     */
    public static void calculateEachCarDisPrice(List<CarPromotionWrapper> carPromotionWrapperList, boolean vip, boolean newCustms, boolean distribution) {
        for (CarPromotionWrapper carPromotionWrapper : carPromotionWrapperList) {
            ShoppingCarBasicData car = carPromotionWrapper.getCarBasicData();
            BigDecimal quantity = new BigDecimal(car.getQuantity());
            BigDecimal productPrice = car.getSalesPrice().multiply(quantity);
            BigDecimal specialPrice = BigDecimal.ZERO;
            BigDecimal packDisPrice = BigDecimal.ZERO;
            BigDecimal newCustomDisPrice = BigDecimal.ZERO;
            BigDecimal vipDisPrice = BigDecimal.ZERO;
            BigDecimal bmdismDisPrice = BigDecimal.ZERO;
            //自选包
            if (PromotionType.Pack.equals(car.getSalesType())) {
                BigDecimal packAmount = new BigDecimal(carPromotionWrapper.getPackAmount());
                BigDecimal ordinaryAmount = new BigDecimal(car.getQuantity() - carPromotionWrapper.getPackAmount());
                packDisPrice = car.getSalesPrice().multiply(packAmount).subtract(carPromotionWrapper.getPackPrice());
                if (vip) {
                    vipDisPrice = car.getSalesPrice().subtract(car.getVipPrice()).multiply(ordinaryAmount);
                }
                if (distribution) {
                    vipDisPrice = car.getSalesPrice().subtract(car.getDistributionPrice()).multiply(ordinaryAmount);
                }
                if (!carPromotionWrapper.getProductPack().getUseCoupon() || car.isSpecial()) {
                    specialPrice = productPrice.subtract(packDisPrice).subtract(vipDisPrice);
                }
            } else if (PromotionType.Bmdism.equals(car.getSalesType())) {
                bmdismDisPrice = car.getSalesPrice().subtract(car.getRealSalesPrice().multiply(carPromotionWrapper.getBestLadder().getDisCount()))
                        .multiply(quantity);
                if (car.isSpecial()) {
                    specialPrice = car.getRealSalesPrice().multiply(carPromotionWrapper.getBestLadder().getDisCount()).multiply(quantity);
                }
            } else if (PromotionType.Ordinary.equals(car.getSalesType())) {
                if (newCustms && car.getNewCustomPrice().compareTo(BigDecimal.ZERO) > 0) {
                    newCustomDisPrice = newCustomDisPrice.add(car.getSalesPrice().subtract(car.getNewCustomPrice()));
                    if (car.isSpecial()) {
                        specialPrice = car.getNewCustomPrice().add(car.getRealSalesPrice().multiply(quantity.subtract(BigDecimal.ONE)));
                    }
                    vipDisPrice = car.getSalesPrice().subtract(car.getRealSalesPrice()).multiply(quantity.subtract(BigDecimal.ONE));
                } else {
                    if (car.isSpecial()) {
                        specialPrice = car.getRealSalesPrice().multiply(quantity);
                    }
                    vipDisPrice = car.getSalesPrice().subtract(car.getRealSalesPrice()).multiply(quantity);
                }

            } else if (PromotionType.GroupBuying.equals(car.getSalesType())) {
                if (car.isSpecial()) {
                    specialPrice = car.getRealSalesPrice().multiply(quantity);
                }
                vipDisPrice = car.getSalesPrice().subtract(car.getRealSalesPrice()).multiply(quantity);
            }
            ShoppingCarDisPrice carDisPrice = new ShoppingCarDisPrice();
            carDisPrice.setCarId(car.getCarId());
            carDisPrice.setProductPrice(productPrice);
            carDisPrice.setPackDisPrice(packDisPrice);
            carDisPrice.setBmdismDisPrice(bmdismDisPrice);
            carDisPrice.setNewCustomDisPrice(newCustomDisPrice);
            carDisPrice.setSpecialPrice(specialPrice);
            carDisPrice.setVipDisPrice(vipDisPrice);
            carPromotionWrapper.setCarDisPrice(carDisPrice);

        }

    }

    /**
     * 分摊金额
     * 分摊顺序
     * 满减-》优惠券-》运费-》成长金
     */
    public static void apportionMjAndCouponAndExpressAndAccountPrice(List<CarPromotionWrapper> carList, BigDecimal manjianPrice, BigDecimal couponPrice,
                                                                     BigDecimal expressPrice, BigDecimal accountPrice) {
        if (manjianPrice != null) {

            apportionPrice(carList, null, manjianPrice, 1);
        }
        if (couponPrice != null) {
            apportionPrice(carList, null, couponPrice, 2);
        }
        if (expressPrice != null) {
            apportionPrice(carList, null, expressPrice, 3);
        }
        if (accountPrice != null) {
            apportionPrice(carList, null, accountPrice, 4);
        }
    }


    /**
     * 分摊金额
     *
     * @param carPromotionWrapperList 购物车 包装类
     * @param priceForApportion       参与分摊总金额
     * @param apportionPrice          待分摊的金额
     * @param apportion               分摊哪个金额       1： 满减。2：优惠券 3：运费 4: 成长金
     */
    private static void apportionPrice(List<CarPromotionWrapper> carPromotionWrapperList, BigDecimal priceForApportion, BigDecimal apportionPrice, int apportion) {
        if (apportionPrice.compareTo(BigDecimal.ZERO) == 0) {
            return;
        }
        List<CarPromotionWrapper> collect = carPromotionWrapperList.stream().filter(carPromotionWrapper -> {
            if (apportion == 2 && !carPromotionWrapper.isUserCoupon()) {
                return false;
            }
            ShoppingCarBasicData car = carPromotionWrapper.getCarBasicData();
            return getPredicateForApportionPrice(apportion, car);
        }).collect(Collectors.toList());

        priceForApportion = getTotalPriceForApportion(collect, apportion);
        BigDecimal lastApportionPrice = apportionPrice;
        for (int i = 0; i < collect.size(); i++) {
            CarPromotionWrapper car = collect.get(i);
            PromotionType salesType = car.getCarBasicData().getSalesType();
            BigDecimal shareDisPrice;
            if (i == collect.size() - 1) {
                shareDisPrice = lastApportionPrice;
            } else {
                BigDecimal price = getCarPriceForApportion(car, apportion);
                BigDecimal apportionDisPrice = null;
                if (priceForApportion.compareTo(apportionPrice) == 0) {
                    apportionDisPrice = price;
                } else {
                    apportionDisPrice = price.divide(priceForApportion, 2, BigDecimal.ROUND_DOWN).multiply(apportionPrice).setScale(2,
                            BigDecimal.ROUND_DOWN);
                }
                lastApportionPrice = lastApportionPrice.subtract(apportionDisPrice);
                shareDisPrice = apportionDisPrice;
            }
            if (apportion == 1) {
                car.getCarDisPrice().setManjianDisPrice(shareDisPrice);
            } else if (apportion == 2) {
                car.getCarDisPrice().setYhqDisPrice(shareDisPrice);
            } else if (apportion == 3) {
                car.getCarDisPrice().setExpressPrice(shareDisPrice);
            } else if (apportion == 4) {
                car.getCarDisPrice().setAccountDisPrice(shareDisPrice);
            }

        }
    }

    /**
     * 过滤条件
     *
     * @param apportion 分摊哪个金额       1： 满减。2：优惠券 3：运费 4: 成长金
     * @param car       购物车
     * @return boolean
     */
    private static boolean getPredicateForApportionPrice(int apportion, ShoppingCarBasicData car) {

        if (PromotionType.ManZeng.equals(car.getSalesType())) {
            return false;
        }
        //优惠券需过滤特例品
        if (apportion == 2 && car.isSpecial()) {
            return false;
        }
        return car.getRealSalesPrice().compareTo(BigDecimal.ZERO) != 0;

    }

    /**
     * 获取参与分摊的总金额
     *
     * @return BigDecimal
     */
    private static BigDecimal getTotalPriceForApportion(List<CarPromotionWrapper> carList, int apportion) {
        return carList.stream().map(carPromotionWrapper -> getCarPriceForApportion(carPromotionWrapper, apportion))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取当前购物车明细金额，用于分摊金额
     *
     * @param carModelWithPTag 购物车
     * @param apportion        分摊哪一金额    1： 满减。2：优惠券 3：运费 4: 成长金
     * @return BigDecimal
     */
    private static BigDecimal getCarPriceForApportion(CarPromotionWrapper carModelWithPTag, int apportion) {
        ShoppingCarDisPrice carDisPrice = carModelWithPTag.getCarDisPrice();
        BigDecimal subtract = carDisPrice.getProductPrice().subtract(carDisPrice.getPackDisPrice()).subtract(carDisPrice.getBmdismDisPrice())
                .subtract(carDisPrice.getNewCustomDisPrice()).subtract(carDisPrice.getVipDisPrice());
        if (apportion == 1) {
            //满减
        } else if (apportion == 2) {
            //优惠券
            subtract = subtract.subtract(carDisPrice.getManjianDisPrice()).subtract(carDisPrice.getSpecialPrice());
        } else if (apportion == 3) {
            //运费
            subtract = subtract.subtract(carDisPrice.getManjianDisPrice()).subtract(carDisPrice.getYhqDisPrice());
        } else if (apportion == 4) {
            //成长金
            subtract = subtract.subtract(carDisPrice.getManjianDisPrice()).subtract(carDisPrice.getYhqDisPrice()).add(carDisPrice.getExpressPrice());
        } else {
            subtract = subtract.subtract(carDisPrice.getManjianDisPrice()).subtract(carDisPrice.getYhqDisPrice()).subtract(carDisPrice.getAccountDisPrice())
                    .add(carDisPrice.getExpressPrice());

        }
        return subtract;
    }
}
